《Kotlin 实战》第3章笔记

Kotlin 实战笔记

集合

Kotlin 的集合分为可变集合和不可变集合,不可变集合类似 Java 中的 List、Set、Map,而可变集合如 MutableList、MutableSet、MutableMap<K, V>。

1
2
3
4
5
6
7
8
9
10
11
val set1 = setOf(1, 2, 3)
val set2 = hashSetOf(1, 2, 3)
val set3 = mutableSetOf(1, 2, 3)

val list1 = listOf(1, 2, 3)
val list2 = arrayListOf(1, 2, 3)
val list3 = mutableListOf(1, 2, 3)

val map1 = mapOf(1 to "one", 2 to "two", 3 to "three")
val map2 = hashMapOf(1 to "one", 2 to "two", 3 to "fifty-three")
val map3 = mutableMapOf(1 to "one", 2 to "two", 3 to "three")

默认参数值

Kotlin 中声明的函数可以指定默认的参数值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fun <T> joinToString(
collection: Collection<T>,
//下面三个参数都有默认值
separator: String = "",
prefix: String = "",
postfix: String = ""
) {}

fun main(args: Array<String>) {
val list = listOf(1, 2, 3)

//有默认值的参数可以不传值
joinToString(list)
joinToString(list, "")
joinToString(list, "", "")
joinToString(list, "", "", "")
}

上面这个例子中 joinToString(list, "", "", "") 的调用可以做得更优雅:

1
2
//调用时标明参数的名称
joinToString(list, separator = "", prefix = "", postfix = "")

注意:在调用一个函数时,如果指定了一个参数名称,那么之后的所有参数都需要标明名称:

1
2
3
4
5
//正确示例
joinToString(list, "", prefix = "", postfix = "")

//错误示例
joinToString(list, separator = "", "", postfix = "")

顶层函数和属性

在 Kotlin 中可以直接在一个 Kotlin 文件声明函数和属性,不必像 Java 那样必须在类中才能声明属性和方法。

1
2
3
4
5
6
7
8
9
10
//文件名:KotlinTest.kt
package com.itscoder.ljuns.practise.kotlin.chapter3
//类似于 Java 中 private static final test1 = 0;
val test1: Int = 0
//类似于 Java 中 public static final test2 = 0;
const val test2: Int = 0
//类似于 Java 中 private static int test3;
var test3: Int = 0
//类似于 Java 中 public static final void test() {}
fun test() {}

看看编译后生成的文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//类名就是文件名
public final class KotlinTestKt {
private static final int test1 = 0;
public static final int test2 = 0;
private static int test3;

public static final int getTest1() {
return test1;
}

public static final int getTest3() {
return test3;
}

public static final void setTest3(int var0) {
test3 = var0;
}

public static final void test() {
}
}

拓展函数和属性

拓展函数

Kotlin 可以在不修改源代码的情况下给原有的类添加函数,即拓展函数。

新建一个 kotlin 文件 StringUtil.kt:

1
2
3
4
5
6
7
8
/**
* 给 String 类拓展了一个 lastChar() 的函数,拓展函数名可以和成员函数名相同
* String:接收者类型,即要拓展的类或接口
* this:接收者对象,可省略
*/
fun String.lastChar(): Char = this.get(this.length - 1)
// 省略 this
fun String.lastChar(): Char = get(length - 1)

上面代码给 String 这个类拓展了一个返回最后一个字符的函数,用法和其他普通函数一样:

1
print("Kotlin".lastChar())

编译后生成的 Java 文件:

1
2
3
4
5
6
public final class StringUtilKt {
public static final char lastChar(@NotNull String $receiver) {
Intrinsics.checkParameterIsNotNull($receiver, "$receiver");
return $receiver.charAt($receiver.length() - 1);
}
}

所以,如果是在 Java 中调用的话就是这样:

1
System.out.println(StringUtilKt.lastChar("Java"));

此外,拓展函数不能被重写,举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
open class View {
open fun click() = println("view click")
}
// 继承 View
open class Button: View() {
// 重写 click()
override fun click() = println("button click")
}

// 分别有拓展函数
fun View.showOff() = println("I`m a View")
fun Button.showOff() = println("I`m a Button")

fun main(args: Array<String>) {
val view: View = Button()

view.click() // 打印结果:button click
// 调用拓展函数时变量类型由静态类型决定,即 View
view.showOff() // 打印结果:I`m a View
View().showOff() // 打印结果:I`m a View
Button().showOff() // 打印结果:I`m a Button
}

注意:如果一个类的成员函数和拓展函数有相同的函数名,成员函数会被优先使用

拓展属性

和拓展属性类似,可以给已存在的类添加拓展属性。

在拓展函数的例子中添加拓展属性:

1
2
3
4
5
6
/**
* 给 String 类拓展了一个 lastChar 的属性,拓展属性名可以和成员属性名相同
* 必须提供对应的 gettr()、setter() 方法
*/
val String.lastChar: Char
get() = get(length - 1)

可变参数

Kotlin 中可变参数的定义和使用与 Java 有点不同:

1
2
3
4
5
6
7
8
9
// 用 vararg 来声明可变参数
fun test(vararg value: String) = println(value.size)

fun main(args: Array<String>) {
// 这种调用和 Java 中一样
test("one", "two", "three")
// Kotlin 不允许传入一个数组,要加一个特殊符号 *
test(*args)
}

看看编译后的文件:

1
2
3
4
5
6
7
8
9
10
11
public static final void test(@NotNull String... value) {
Intrinsics.checkParameterIsNotNull(value, "value");
int var1 = value.length;
System.out.println(var1);
}

public static final void main(@NotNull String[] args) {
Intrinsics.checkParameterIsNotNull(args, "args");
test("one", "two", "three");
test((String[])Arrays.copyOf(args, args.length));
}

所以如果在 Java 中去调用 Kotlin 定义的可变参数,使用方式还是和以前一样的。

坚持原创技术分享,您的支持将鼓励我继续创作!